class test{
  constructor(string){
    this.curr = {}
    this.arr = [
      { type: 'let', value: 'let' },
      { type: 'IDENTIFIER', value: 'bianl' },
      { type: 'SIMPLE_ASSIGN', value: '=' },
      { type: 'STRING', value: "'155'" },
      // { type: ';', value: ';' },
      { type: 'let', value: 'let' },
      { type: 'IDENTIFIER', value: 'num' },
      { type: 'SIMPLE_ASSIGN', value: '=' },
      { type: 'NUMBER', value: '15' },
      // { type: ';', value: ';' },
      { type: 'function', value: 'function' },
      { type: 'IDENTIFIER', value: 'asd' },
      { type: '(', value: '(' },
      { type: 'IDENTIFIER', value: 'par' },
      { type: ')', value: ')' },
      { type: '{', value: '{' },

      { type: 'let', value: 'let' },
      { type: 'IDENTIFIER', value: 'xxxx' },
      { type: 'SIMPLE_ASSIGN', value: '=' },
      { type: 'NUMBER', value: 'x1c2' },


      { type: 'return', value: 'return' },
      { type: 'IDENTIFIER', value: 'num' },

      // { type: ';', value: ';' },
      { type: '}', value: '}' },
      // { type: ';', value: ';' },
      null
    ]
    // this.eat()
    
  }
  StatementList(){
    console.log(this.curr);
    
    const statementList = []
    this.eat()
    while(this.curr != null){
      statementList.push(this.statement())
    }
    this.eat()
    return {
      type:'body',
      body:statementList
    }
  }
  statement(){
    switch(this.curr.type){
      case 'let':
        return this.VariableStatement();
      case 'function':
        return this.functionVariable();
      case '{1':
        return this.StatementList()
      case 'return':
        return this.setReturn()
      default:
        this.eat()
    }
  }
  run(){
    // this.eat()
    return this.StatementList()
  }
  setReturn(){
    console.log(this.curr);
    
    this.eat();
    let argument;
    if(this.curr.type ==='IDENTIFIER'){
      argument = this.identifier()
    }
    return {
      type:'return',
      argument
    }
  }
  functionVariable(){
    this.eat();
    const id = this.identifier();
    const params = this.funParams();
    const body= this.StatementList();
    return {
      type:'function',
      id,
      params,
      body
    }
  }
  funParams(){
    this.eat();//(
    const result = [];
    while(this.curr !== null && this.curr.type !==')'){
      result.push(this.identifier())
    }
    this.eat();//)
    return result
  }
  VariableStatement(){
    this.eat();
    const id = this.identifier();
    let init;
    if(this.curr.type ==='SIMPLE_ASSIGN'){
      this.eat();
      init = this.VariableInit();
    }
    return {
      type:'Variable',
      id,
      init,
    }
  }
  VariableInit(){
    let type,value;
    if(this.getValueType()){
      type = 'Literal'
      value = this.curr.value
    }
    return {
      type,
      value
    }
  }
  getValueType(){
    const types = [
      'STRING',
      'NUMBER'
    ]
    
    return this.curr == null ? null :types.includes(this.curr.type)
  }
  identifier(){
    const name = this.curr.value;
    this.eat();
    return {
      type:'IDENTIFIER',
      name
    }
  }
  eat(){
    this.curr = this.arr.shift();
    
  }

}

console.log(JSON.stringify(new test().run()));
